0X00 前言

从大一开始就读过网上的各种关于 SSL 分析的文章,但是由于知识水平的不到位,也只是似懂非懂的,能说个大概但是再细节一点就懵逼了,不过上学期学了密码学,学的时候我就特地的对有关这部分的内容重点关注了一下,想这次必须要彻底弄清楚了,并且 SSL 也是我们当前互联网的加密传输与通信的典范案例,弄清楚细节对日后的学习工作必有大的帮助。

SSL利用数据加密(对称密码)、身份验证(数字签名+PKI/CA)和消息完整性验证机制(MAC),为基于TCP等可靠连接的应用层协议提供安全性保证。本文会简单介绍SSL的产生背景、技术优点、安全机制及工作过程。

注: PKI (Public Key Infrastructure 公钥基础设施)

0X01 产生背景

说的简单一点,其实就是随着互联网的发展,互联网能帮我们实现越来越多的操作,比如支付,转账等,这种敏感信息在网上传播如果没有保护是很危险的(传统的万维网协议HTTP不具备安全机制——采用明文的形式传输数据、不能验证通信双方的身份、无法防止传输的数据被篡改等),信息不仅仅在传输过程中会被窃听,甚至你对其一万个放心的输入自己支付密码的网站本身就是伪造的,所以我们必须找到一种方式来确认互联网中交互双方的身份,并且能保证数据在传输过程中是加密的,防止遭受窃听攻击,于是乎 SSL 就出现了,它利用数据加密、身份验证和消息完整性验证机制,为网络上数据的传输提供安全性保证。

0X02 技术优点

SSL支持各种应用层协议。虽然 SSL 设计的初衷是为了解决万维网安全性问题,但是由于SSL 位于应用层和传输层之间,如下图所示,它可以为任何基于TCP等可靠连接的应用层协议提供安全性保证。

此处输入图片的描述

0X03 安全机制

SSL协议实现的安全机制包括:

(1)数据传输的机密性:利用对称密钥算法对传输的数据进行加密。
(2)身份验证机制:基于证书利用数字签名方法对服务器和客户端进行身份验证,其中客户端的身份验证是可选的。
(3)消息完整性验证:消息传输过程中使用 MAC 算法来检验消息的完整性。

3.1数据传输的机密性

网络上传输的数据很容易被非法用户窃取,SSL采用在通信双方之间建立加密通道的方法保证数据传输的机密性。所谓加密通道,是指发送方在发送数据前,使用加密算法和加密密钥对数据进行加密,然后将数据发送给对方,接收方接收到数据后,利用解密算法和解密密钥从密文中获取明文。没有解密密钥的第三方,无法将密文恢复为明文,从而保证数据传输的机密性。

加解密算法分为两类:
(1)对称密钥算法:数据加密和解密时使用相同的密钥。
(2)非对称密钥算法:数据加密和解密时使用不同的密钥,一个是公开的公钥,一个是由用户秘密保存的私钥。利用公钥(或私钥)加密的数据只能用相应的私钥(或公钥)才能解密。

两者的比较和适用范围:

与非对称密钥算法相比,对称密钥算法具有计算速度快的优点,通常用于对大量信息进行加密(如对所有报文加密),而非对称密钥算法,一般用于数字签名和对较少的信息进行加密。

SSL加密通道上的数据加解密使用对称密钥算法,目前主要支持的算法有DES、3DES、AES等,这些算法都可以有效地防止交互数据被窃听。对称密钥算法要求解密密钥和加密密钥完全一致。因此,利用对称密钥算法加密传输数据之前,需要在通信两端部署相同的密钥(这里使用的是非对称密钥算法,通常是RSA进行交换)。详细的对称密钥的部署方法请看后面的 3.4 利用非对称密钥算法保证密钥本身的安全

3.2 身份验证机制

电子商务和网上银行等应用中必须保证要登录的Web服务器是真实的,以免重要信息被非法窃取。SSL利用数字签名来验证通信对端的身份。非对称密钥算法可以用来实现数字签名。由于通过私钥加密后的数据只能利用对应的公钥进行解密,因此根据解密是否成功,就可以判断发送者的身份,如同发送者对数据进行了“签名”。例如,Alice使用自己的私钥对一段固定的信息加密后发给Bob,Bob利用Alice的公钥解密,如果解密结果与固定信息相同,那么就能够确认信息的发送者为Alice,这个过程就称为数字签名。

SSL客户端必须验证SSL服务器的身份,SSL服务器是否验证SSL客户端的身份,则由SSL服务器决定。SSL客户端和SSL服务器的身份验证过程,请看后面的 4.2 SSL握手过程。

使用数字签名验证身份时,需要确保被验证者的公钥是真实的,否则,非法用户可能会冒充被验证者与验证者通信。所下图所示,Cindy冒充Bob,将自己的公钥发给Alice,并利用自己的私钥计算出签名发送给Alice,Alice利用“Bob”的公钥(实际上为Cindy的公钥)成功验证该签名,则Alice认为Bob的身份验证成功,而实际上与Alice通信的是冒充Bob的Cindy。SSL利用PKI提供的机制保证公钥的真实性,详细介绍请看后面的 3.5 利用PKI保证公钥的真实性。

此处输入图片的描述

3.3 消息完整性验证

为了避免网络中传输的数据被非法篡改,SSL利用基于MD5或SHA的MAC算法来保证消息的完整性。MAC算法是在密钥参与下的(这是与普通的 hash 最大的不同,可以简单理解为带密钥的 hash )数据摘要算法,能将密钥和任意长度的数据转换为固定长度的数据。利用MAC算法验证消息完整性的过程如图2所示。发送者在密钥的参与下,利用MAC算法计算出消息的MAC值,并将其加在消息之后发送给接收者。接收者利用同样的密钥和MAC算法计算出消息的MAC值,并与接收到的MAC值比较。如果二者相同,则报文没有改变;否则,报文在传输过程中被修改,接收者将丢弃该报文。

此处输入图片的描述

MAC算法具有如下特征,使其能够用来验证消息的完整性:

(1)消息的任何改变,都会引起输出的固定长度数据产生变化。通过比较MAC值,可以保证接收者能够发现消息的改变。
(2)MAC 算法需要密钥的参与,因此没有密钥的非法用户在改变消息的内容后,无法添加正确的MAC值,从而保证非法用户无法随意修改消息内容。

MAC算法要求通信双方具有相同的密钥,否则MAC值验证将会失败。因此,利用MAC算法验证消息完整性之前,需要在通信两端部署相同的密钥。MAC密钥的部署方法同样请见下面一节 3.4 利用非对称密钥算法保证密钥本身的安全。

3.4 利用非对称密钥算法保证密钥本身的安全

上面已经讲到,对称密钥算法和MAC算法要求通信双方具有相同的密钥,否则解密或MAC值验证将失败。因此,要建立加密通道或验证消息完整性,必须先在通信双方部署一致的密钥。

SSL利用非对称密钥算法加密密钥的方法实现密钥交换,保证第三方无法获取该密钥。如图3所示,SSL客户端(如Web浏览器)利用SSL服务器(如Web服务器)的公钥加密密钥,将加密后的密钥发送给SSL服务器,只有拥有对应私钥的SSL服务器才能从密文中获取原始的密钥。SSL通常采用RSA算法加密传输密钥

此处输入图片的描述

注意:

(1)实际上,SSL 客户端发送给SSL服务器的密钥不能直接用来加密数据或计算MAC值,该密钥是用来计算对称密钥和MAC密钥的信息,称为premaster secret。SSL客户端和SSL 服务器利用premaster secret计算出相同的主密钥(master secret),再利用master secret 生成用于对称密钥算法、MAC算法等的密钥。premaster secret 是计算对称密钥、MAC 算法密钥的关键。

(2)用来实现密钥交换的算法称为密钥交换算法。非对称密钥算法RSA 用于密钥交换时,也可以称之为密钥交换算法

也就是说,如果仔细研究的话就会知道 premaster secret 并不是真正的对称密钥,真正的对称密钥叫做master secret ,是由 premaster secret 和 客户端以及服务器分别产生的参数计算而成的,计算的方法如下

此处输入图片的描述

那么这个 random 是哪里来的呢?实际上是在 SSL 握手的过程中产生的,由于这部分内容在后面的 4.1 只验证服务器的 SSL 握手过程 的补充部分将会讲到,这里就不再详细阐述。

利用非对称密钥算法加密密钥之前,发送者需要获取接收者的公钥,并保证该公钥确实属于接收者,否则,密钥可能会被非法用户窃取。如图一所示,Cindy冒充Bob,将自己的公钥发给Alice,Alice利用Cindy的公钥加密发送给Bob的数据,Bob由于没有对应的私钥无法解密该数据,而Cindy截取数据后,可以利用自己的私钥解密该数据。SSL利用PKI提供的机制保证公钥的真实性,详细介绍请看下一节 3.5 利用PKI保证公钥的真实性

3.5 利用PKI保证公钥的真实性

PKI通过数字证书来发布用户的公钥,并提供了验证公钥真实性的机制。数字证书(简称证书)是一个包含用户的公钥及其身份信息的文件,证明了用户与公钥的关联。数字证书由权威机构——CA签发,并由CA保证数字证书的真实性。

SSL客户端把密钥加密传递给SSL服务器之前,SSL服务器需要将从CA获取的证书发送给SSL客户端,SSL客户端通过PKI判断该证书的真实性。如果该证书确实属于SSL服务器,则利用该证书中的公钥加密密钥,发送给SSL服务器。

验证SSL服务器/SSL客户端的身份之前,SSL服务器/SSL客户端需要将从CA获取的证书发送给对端,对端通过PKI判断该证书的真实性。如果该证书确实属于SSL服务器/SSL客户端,则对端利用该证书中的公钥验证SSL服务器/SSL客户端的身份。

0X04 协议工作过程

协议最主要的过程就是密钥协商,SSL通过握手过程在客户端和服务器之间协商会话参数,并建立会话。会话包含的主要参数有会话ID、对方的证书、加密套件(密钥交换算法、数据加密算法和MAC算法等)以及主密钥(master secret)。通过SSL会话传输的数据,都将采用该会话的主密钥和加密套件进行加密、计算MAC等处理。

不同情况下,SSL握手过程存在差异。下面将分别描述以下三种情况下的握手过程:

  • 只验证服务器的 SSL 握手过程
  • 验证服务器和客户端的 SSL 握手过程
  • 恢复原有会话的 SSL 握手过程

4.1 只验证服务器的 SSL 握手过程

这种方式应该是我们每天上网都在进行的,所以放在第一个

此处输入图片的描述

如图5所示,只需要验证SSL服务器身份,不需要验证SSL客户端身份时,SSL的握手过程为:

(1) SSL 客户端通过Client Hello 消息将它支持的SSL 版本、加密算法、密钥交换算法、MAC 算法等信息发送给SSL 服务器。

(2) SSL 服务器确定本次通信采用的SSL 版本和加密套件,并通过Server Hello消息通知给SSL 客户端。如果SSL 服务器允许SSL客户端在以后的通信中重用本次会话,则SSL服务器会为本次会话分配会话ID,并通过Server Hello 消息发送给SSL 客户端。

(3) SSL 服务器将携带自己公钥信息的数字证书通过Certificate 消息发送给SSL客户端。

(4) SSL 服务器发送Server Hello Done 消息,通知SSL客户端版本和加密套件协商结束,开始进行密钥交换。

(5) SSL 客户端验证SSL 服务器的证书合法后,利用证书中的公钥加密SSL 客户端随机生成的premaster secret,并通过Client Key Exchange 消息发送给SSL 服务器。

(6) SSL 客户端发送Change Cipher Spec 消息,通知SSL 服务器后续报文将采用协商好的密钥和加密套件进行加密和MAC 计算。

(7) SSL 客户端计算已交互的握手消息(除Change Cipher Spec 消息外所有已交互的消息)的Hash 值,利用协商好的密钥和加密套件处理Hash 值(计算并添加MAC 值、加密等),并通过Finished 消息发送给SSL 服务器。SSL服务器利用同样的方法计算已交互的握手消息的Hash 值,并与Finished 消息的解密结果比较,如果二者相同,且MAC 值验证成功,则证明密钥和加密套件协商成功。

(8) 同样地,SSL 服务器发送Change Cipher Spec 消息,通知SSL 客户端后续报文将采用协商好的密钥和加密套件进行加密和MAC 计算。

(9) SSL 服务器计算已交互的握手消息的Hash 值,利用协商好的密钥和加密套件处理Hash 值(计算并添加MAC 值、加密等),并通过Finished 消息发送给SSL 客户端。SSL 客户端利用同样的方法计算已交互的握手消息的
Hash 值,并与Finished 消息的解密结果比较,如果二者相同,且MAC 值验证成功,则证明密钥和加密套件协商成功。

SSL客户端接收到SSL服务器发送的Finished消息后,如果解密成功,则可以判断SSL服务器是数字证书的拥有者,即SSL服务器身份验证成功,因为只有拥有私钥的SSL服务器才能从Client Key Exchange消息中解密得到premaster secret,从而间接地实现了SSL客户端对SSL服务器的身份验证。

注意:

(1)Change Cipher Spec 消息属于SSL 密码变化协议,其他握手过程交互的消息均属于SSL 握手协议,统称为SSL握手消息。
(2)计算 Hash 值,指的是利用Hash 算法(MD5 或SHA)将任意长度的数据转换为固 定长度的数据。

可能上面的过程过于复杂和理论化,图片对整个过程的展示也不够清晰,于是为了更直观地弄清楚我建议结合下面这幅图帮助大家理解

此处输入图片的描述

这幅图是使用 RSA 来协商密钥的一个实际的例子(之前说过了我们需要使用公钥来协商用来加密的对称密码的密钥)。

(1) 客户端首先产生一个随机数 client random 发给服务器端

(2)服务器端也产生一个随机数 server random 并且将自己经过 CA 认证的证书(里面保存着自己的RSA公钥)连同 server random 一起发给客户端

(3)客户端验证 CA 的签名无误后,确认这个公钥来源于服务器端,那么就打开证书取出其中的 RSA 公钥,然后产生另一个随机数 premaster secret (这是整个过程中的第三个随机数) ,使用 RSA 公钥加密这个 premaster secret 发送给服务器端

(4)服务器端使用自己的私钥解密得到 premaster secret

(5)双方现在都拥有了三个随机数 client random 、server random 、premaster secret ,然后双方都使用我在 3.4 节提到的算法计算出双方的共享密钥 session key

补充:

因为这个图是来源于 CloudFlare,我们知道该公司主要提供的是 CDN 加速服务,也就是说客户端是直接和该公司提供的 CDN 服务器进行交互的,但是出于安全考虑,我们又不能把私钥交给CDN服务商,那这种密钥的交换是怎么实现的呢,如下图所示:

此处输入图片的描述

我们设立了一个专门的密钥服务器,所有的 CDN 服务器都要与密钥服务器交互来实现使用私钥解密公钥加密的 premaster secret

4.2 验证服务器和客户端的SSL握手过程

此处输入图片的描述

SSL客户端的身份验证是可选的,由SSL服务器决定是否验证SSL客户端的身份。如图6中蓝色部分标识的内容所示,如果SSL服务器验证SSL客户端身份,则SSL服务器和SSL客户端除了交互 4.1 只验证服务器的SSL握手过程 中的消息协商密钥和加密套件外,还需要进行以下操作:

(4) SSL 服务器发送Certificate Request 消息,请求SSL 客户端将其证书发送给SSL 服务器。

(6) SSL 客户端通过Certificate 消息将携带自己公钥的证书发送给SSL 服务器。SSL 服务器验证该证书的合法性。

(8) SSL 客户端计算已交互的握手消息、主密钥的Hash 值,利用自己的私钥对 其进行加密,并通过Certificate Verify 消息发送给SSL 服务器。

SSL 服务器计算已交互的握手消息、主密钥的Hash 值,利用SSL 客户端证书中的公钥解密Certificate Verify 消息,并将解密结果与计算出的Hash 值比较。如果二者相同,则SSL 客户端身份验证成功

4.3 恢复原有会话的SSL握手过程

此处输入图片的描述

协商会话参数、建立会话的过程中,需要使用非对称密钥算法来加密密钥、验证通信对端的身份,计算量较大,占用了大量的系统资源。为了简化SSL握手过程,SSL允许重用已经协商过的会话

具体过程为:

(1) SSL 客户端发送Client Hello 消息,消息中的会话ID 设置为计划重用的会话的ID。

(2) SSL 服务器如果允许重用该会话,则通过在Server Hello 消息中设置相同的会话ID 来应答。这样,SSL 客户端和SSL 服务器就可以利用原有会话的密钥和加密套件,不必重新协商。

(3) SSL 客户端发送Change Cipher Spec 消息,通知SSL 服务器后续报文将采用原有会话的密钥和加密套件进行加密和MAC 计算。

(4) SSL 客户端计算已交互的握手消息的Hash 值,利用原有会话的密钥和加密套件处理Hash 值,并通过Finished 消息发送给SSL 服务器,以便SSL 服务器判断密钥和加密套件是否正确。

(5) 同样地,SSL 服务器发送Change Cipher Spec 消息,通知SSL 客户端后续报文将采用原有会话的密钥和加密套件进行加密和MAC 计算。

(6) SSL 服务器计算已交互的握手消息的Hash 值,利用原有会话的密钥和加密套件处理Hash 值,并通过Finished 消息发送给SSL 客户端,以便SSL 客户端判断密钥和加密套件是否正确。

0X05 总结

花了一点时间简单的总结、梳理和归纳了一下 SSL 协议,也希望日后的工作学习中能有所参考

0X06 参考链接

https://www.linuxidc.com/Linux/2015-07/120230.htm
http://www.ruanyifeng.com/blog/2014/09/illustration-ssl.html
https://blog.cloudflare.com/keyless-ssl-the-nitty-gritty-technical-details/
https://blog.cloudflare.com/announcing-keyless-ssl-all-the-benefits-of-cloudflare-without-having-to-turn-over-your-private-ssl-keys/